package com.cloud.drore.eboss.login;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloud.drore.eboos.common.base.ResultMessage;
import com.cloud.drore.eboos.common.constant.CommonConstant;
import com.cloud.drore.eboos.common.constant.ResultCodeConstant;
import com.cloud.drore.eboos.common.entity.base.ShiroUser;
import com.cloud.drore.eboos.common.util.UserLocalData;
import com.cloud.drore.eboos.exception.BusinessException;
import com.cloud.drore.eboss.login.token.TokenManager;
import com.cloud.drore.eboss.login.token.TokenModel;
import com.cloud.drore.eboss.login.user.Anon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 浙江卓锐科技股份有限公司 版权所有 © Copyright 2018<br>
 *
 * @Description: <br>
 * @Project: eboos <br>
 * @CreateDate: Created in 2018/3/26 9:23 <br>
 * @Author: <a href="836327318@qq.com">吴昌益</a>
 */
@Component
public class AuthorizationInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    @Qualifier(value = "redisTokenManager")
    private TokenManager manager;

    private static Set<String> set = new HashSet<>();

    private static String AUTHOR_ERROR = "验证token失败，请重新登录！！";

    static {
        set.add("/");
        set.add("/login");
        set.add("/admin/onekey");
    }


    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        //如果不是映射到方法直接通过
        String servletPath = request.getRequestURI();
        if("OPTIONS".equals(request.getMethod()) || set.contains(servletPath)||servletPath.contains("swagger")||servletPath.contains("/v2/api-docs"))
            return true;

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        //判断是不是忽列请求
        if (method.getAnnotation(Anon.class) != null ||method.getDeclaringClass().getAnnotation(Anon.class)!=null) {
            return true;
        }
        //从header中得到token
        String authorization = request.getHeader(CommonConstant.AUTHORIZATION);
        //验证token
        TokenModel model = manager.getToken(authorization);
        if (manager.checkToken(model)) {
            //如果token验证成功，将token对应的用户id存在request中，便于之后注入
            request.setAttribute(CommonConstant.CURRENT_USER_ID, model.getUserId());
            setUser(CommonConstant.CURRENT_USER_ID+model.getUserId());
            return true;
        }
        else{
            String origin = request.getHeader("Origin");
            response.setHeader("Access-Control-Allow-Origin",origin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "5000");
            response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,Token");

            OutputStream outputStream = response.getOutputStream();
            ResultMessage restMessage = new ResultMessage();
            restMessage.setMessage(false);
            restMessage.setCode(ResultCodeConstant.TOKEN_INVALID_ERROR_CODE);
            restMessage.setMessage(AUTHOR_ERROR);
            outputStream.write(JSON.toJSONString(restMessage).getBytes("utf-8"));
            outputStream.flush();
            outputStream.close();
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
//        OutputStream outputStream = httpServletResponse.getOutputStream();
//        BufferedOutputStream bos = new BufferedOutputStream(outputStream);
        ResultMessage restMessage = new ResultMessage();
        restMessage.setMessage(false);
        restMessage.setCode(ResultCodeConstant.TOKEN_INVALID_ERROR_CODE);
        restMessage.setMessage(AUTHOR_ERROR);
//        outputStream.flush();
//        outputStream.write(JSON.toJSONString(restMessage).getBytes("utf-8"),0,100);
//        outputStream.close();

    }

    private void setUser(String key){
        ShiroUser user = JSONObject.parseObject(stringRedisTemplate.opsForValue().get(key), ShiroUser.class);
        UserLocalData.setCurrentUser(user);
    }
}